const { Controller } = require('egg');
const { CozeAPI, COZE_CN_BASE_URL} = require('@coze/api');
const {getAgentToken} = require("../../api/common");
class ChatController extends Controller {
    /**
     * 查看用户问的问题记录chat_log
     */
    async getUserAskLog() {
        const { ctx, app } = this;
        let { page=1,pageSize } = ctx.request.query;
        const res = await app.mysql.select('chat_log', {
            limit:parseInt(pageSize),
            offset: (page - 1) * pageSize,
            orders: [['id', 'desc']],

        })
        for (const item of res) {
            // 根据bot_id 获取 bot_name
            const botInfo = await app.mysql.get('agents', {
                bot_id: item.bot_id,
            });
            if (botInfo) {
                item.bot_name = botInfo.bot_name;
            }
            if (item.user_id) {
                // 根据user_id获取用户信息
                const userInfo = await app.mysql.get('users', {
                    id: item.user_id,
                });
                if (userInfo) {
                    item.user_name = userInfo.username;
                }

            }

        }
        ctx.body = {
            success:true,
            data:res
        }
    }


    /**
     * 获取全部历史消息 查看消息列表
     */
    async getAllHistoryMessage() {
        const { ctx, app } = this;
        let { conversation_id } = ctx.request.query;
        if (!conversation_id) {
            ctx.body = {
                success: false,
                message: '会话ID不能为空'
            };
        }
        const ATRes = await getAgentToken(this,{conversation_id});
        if(!ATRes.success){
            return ATRes;
        }
        const client = new CozeAPI({
            baseURL: COZE_CN_BASE_URL,
            token: ATRes.data,
        });
        try {
            let res = await client.conversations.messages.list(conversation_id);
            ctx.body = {
                success: true,
                data: res
            };
        }catch (e) {
            ctx.body = {
                success: false,
                message: e.message
            };
        }
    }


    /**
     *  清空会话消息 接口
     */
    async clearConversation() {
        const { ctx, app } = this;
        let { conversation_id } = ctx.request.query;
        console.log(conversation_id)
        if (!conversation_id) {
            ctx.body = {
                success: false,
                message: '会话ID不能为空'
            };
        }
        const ATRes = await getAgentToken(this,{conversation_id});
        if(!ATRes.success){
            return ATRes;
        }
        const client = new CozeAPI({
            baseURL: COZE_CN_BASE_URL,
            token: ATRes.data,
        });
        const res = await client.conversations.clear(conversation_id);
        if(res.id){
            ctx.body = {
                success: true,
                data: res
            };
        }else{
            ctx.body = {
                success: false,
                message: res.message
            };
        }
    }


    /**
     * 删除单条消息
     */
    async deleteMessage() {
        const { ctx, app } = this;
        let { conversation_id,message_id } = ctx.request.query;

        const ATRes = await getAgentToken(this,{conversation_id});
        if(!ATRes.success){
            return ATRes;
        }
        const agent_access_token = ATRes.data;
        const client = new CozeAPI({
            baseURL: COZE_CN_BASE_URL,
            token:agent_access_token,
        });
        if (!conversation_id) {
            ctx.body = {
                success: false,
                message: '会话ID不能为空'
            };
        }
        if (!message_id) {
            ctx.body = {
                success: false,
                message: '消息ID不能为空'
            };
        }
        const delRes = client.conversations.messages.delete(conversation_id,message_id);
        if(delRes.code ===0){
            ctx.body = {
                success: true,
                data: delRes
            };
        }else{
            ctx.body = {
                success: false,
                message: delRes.message
            };
        }
    }

    /**
     * https://api.coze.cn/v3/chat/message/list
     * 查看对话消息详情
     * 查看指定对话中除 Query 以外的其他消息，包括模型回复、智能体执行的中间结果等消息。
     * 查看消息列表 API 与查看对话消息详情 API 的区别在于：
     * 查看消息列表 API 用于查询指定会话（conversation）中的所有消息，不仅包括开发者在会话中手动插入的每一条消息，也包括用户的每一次 Query、智能体的每一次回复。
     * 查看对话消息详情 API 通常用于非流式对话场景中，查看某次对话（chat）中 type=answer 的智能体回复及 type=follow-up 等类型的对话中间态消息。
     */
    async getChatMessageById() {
        const { ctx, app } = this;

        let { conversation_id,chat_id } = ctx.request.query;
        const ATRes = await getAgentToken(this,{conversation_id});
        if(!ATRes.success){
            return ATRes;
        }
        const agent_access_token = ATRes.data;
        const client = new CozeAPI({
            baseURL: COZE_CN_BASE_URL,
            token: agent_access_token
        });
        if (!conversation_id) {
            ctx.body = {
                success: false,
                message: '会话ID不能为空'
            };
        }
        if (!chat_id) {
            ctx.body = {
                success: false,
                message: '对话ID不能为空'
            };
        }
        try {
            let chatRes = await client.chat.messages.list(conversation_id,chat_id);
            ctx.body = {
                success: true,
                data: chatRes
            };

        }catch (e) {
            ctx.body = {
                success: false,
                message: e.message
            };
        }
    }

    /**
     * @name 查看对话详情
     * @desc 在非流式会话场景中，调用发起对话接口后，可以先轮询此 API 确认本轮对话已结束（status=completed），再调用接口查看对话消息详情查看本轮对话的模型回复。
     */
    async getChatDetailById() {
        const { ctx, app } = this;


        let { conversation_id,chat_id } = ctx.request.query;
        const ATRes = await getAgentToken(this,{conversation_id});
        if(!ATRes.success){
            return ATRes;
        }
        const agent_access_token = ATRes.data;
        const client = new CozeAPI({
            baseURL: COZE_CN_BASE_URL,
            token: agent_access_token
        });
        if (!conversation_id) {
            ctx.body = {
                success: false,
                message: '会话ID不能为空'
            };
        }
        if (!chat_id) {
            ctx.body = {
                success: false,
                message: '对话ID不能为空'
            };
        }
        try {
            let chatRes = await client.chat.retrieve(conversation_id,chat_id);
            ctx.body = {
                success: true,
                data: chatRes
            };

        }catch (e) {
            ctx.body = {
                success: false,
                message: e.message
            };
        }
    }

    /**
     * 获取缓存中最新消息
     */
    async getCacheMessage() {
        const { ctx, app } = this;
        let { conversation_id,
            bot_id, local_chat_id} = ctx.request.query;
        // console.log(await app.redis.get('chat_is_finished_' + ctx.currentUser.id))
        ctx.set('Cache-Control', 'no-cache');
        const res = await app.redis.get('chat_' + ctx.currentUser.id + '_'+local_chat_id);
        if (res) {
            if(await app.redis.get('chat_is_finished_' + ctx.currentUser.id+ '_'+local_chat_id) ==='1'){
                await app.redis.del('chat_' + ctx.currentUser.id+ '_'+local_chat_id);
                await app.redis.del('chat_is_finished_' + ctx.currentUser.id+ '_'+local_chat_id,)
                // ctx.body = {
                //     success: false,
                //     message: '对话已完成'
                // };
                // return;
            }
            ctx.body = {
                success: true,
                data: res
            };

        } else {
            ctx.body = {
                success: true,
                message: null
            };
        }
    }

    /**
     * 停止当前会话
     */
    async stopChat() {
        const { ctx, app } = this;
        const {conversation_id,chat_id} = ctx.request.query;
        const ATRes = await getAgentToken(this,{conversation_id});
        if(!ATRes.success){
            return ATRes;
        }
        const agent_access_token = ATRes.data;
        // 开始发起对话
        const client = new CozeAPI({
            baseURL: COZE_CN_BASE_URL,
            token: agent_access_token,
        });
        await client.chat.cancel(conversation_id, chat_id);
        ctx.body = {
            success: true,
            message: '已停止对话'
        };
    }


    /**
     * @name 创建消息并发起对话
     * @description 创建消息并发起对话。
     * 1. 调用此接口创建消息，创建消息后，会返回消息 ID。
     * 2. 调用发起对话接口，传入消息 ID，发起对话。
     * 3. 判断用户viptype，若为free，则需要调用接口判断用户是否达到最大对话次数，若达到最大对话次数，则返回错误。
     * 4. 若用户未达到最大对话次数，则调用接口发起对话，发起对话后，会返回对话 ID。
     */
    async createMessageAndChat() {

        const { ctx, app } = this;
        
        if(ctx.currentUser.vip_type === 'free' && ctx.currentUser.free_chat_number <=0){
            ctx.body = {
                success: false,
                message: '您的免费对话次数已用完'
            }
            return;
            // 判断用户是否达到最大对话次数
        }
        if(ctx.currentUser.vip_type === 'month' || ctx.currentUser.vip_type ==='year'){
            // 判断是否到期。
            if(ctx.currentUser.vip_expire_time < Date.now()){
                ctx.body = {
                    success: false,
                    message: '您的VIP已到期'
                }
                return;
            }
        }
        let { conversation_id,content,bot_id,is_stream = true ,local_chat_id} = ctx.request.body;
        if (!conversation_id) {
            ctx.body = {
                success: false,
                message: '会话ID不能为空'
            };
            return;
        }
        if (!content) {
            ctx.body = {
                success: false,
                message: '消息内容不能为空'
            };
            return;
        }
        // bot_id 获取agentInfo
        const ATRes = await getAgentToken(this,{bot_id});
        if(!ATRes.success){
            return ATRes;
        }
        const agent_access_token = ATRes.data;
        // 扣除一点免费对话次数
        if(ctx.currentUser.vip_type === 'free'){
            ctx.currentUser.free_chat_number = ctx.currentUser.free_chat_number - 1;
            await app.mysql.update('users',{
                free_chat_number:ctx.currentUser.free_chat_number
            },{
                where:{
                    id:ctx.currentUser.id
                }
            });
        }
        app.mysql.insert('chat_log',{
            source:'user',
            content,
            bot_id:bot_id,
            user_id:ctx.currentUser.id,
            create_time:new Date()
        })
        // 开始发起对话
        const client = new CozeAPI({
            baseURL: COZE_CN_BASE_URL,
            token: agent_access_token,
        });
        if(is_stream){
            ctx.set('Content-Type', 'text/event-stream; charset=utf-8');
            ctx.set('Cache-Control', 'no-cache');
            ctx.set('Connection', 'keep-alive');

            let stream  = await client.chat.stream({
                conversation_id,
                bot_id,
                user_id: ctx.currentUser.id.toString(),
                additional_messages: [
                    {
                        role:'user',
                        content,
                        content_type:'text',
                    }],
            });
            await app.redis.set('chat_is_finished_' + ctx.currentUser.id+ '_'+local_chat_id, '0','EX', 60 * 60 * 24);
            for await (const part of stream) {
                // ctx.res.write(JSON.stringify(part)+'\r\n');
                let a  = await app.redis.get('chat_' + ctx.currentUser.id+ '_'+local_chat_id);
                await app.redis.set('chat_' + ctx.currentUser.id+ '_'+local_chat_id, (a??'') +  JSON.stringify(part)+'\r\n','EX', 60 * 60 * 24);
                // get
                // ctx.body = await app.redis.get('foo');
                // 防止粘包
                // ctx.res.write('\r\n');
            }
            await app.redis.set('chat_is_finished_' + ctx.currentUser.id+ '_'+local_chat_id, '1','EX', 60 * 60 * 24);
            // 结束流式响应
            // ctx.res.end('0\r\n\r\n');
            ctx.body ={
                success: true,
                data: 'ok'
            }
        }
        else{
            let chatRes = await client.chat.create({
                conversation_id,
                bot_id,
                user_id: ctx.currentUser.id.toString(),
                additional_messages: [
                    {
                        role:'user',
                        content,
                        content_type:'text',
                    }],
            });
            ctx.body = {
                success: true,
                data: chatRes
            };
            return ;
        }
        // console.log(stream)
        // 接收并发送流式响应

        ctx.body = {
            success: true,
            data: 'ok'
        };
    }

    /**
     * 创建消息
     */
    async createMessage() {
        const { ctx, app } = this;

        let { conversation_id,content,bot_id } = ctx.request.body;
        const ATRes = await getAgentToken(this,{bot_id});
        if(!ATRes.success){
            return ATRes;
        }
        const agent_access_token = ATRes.data;
        const client = new CozeAPI({
            baseURL: COZE_CN_BASE_URL,
            token: agent_access_token,
        });
        if (!conversation_id) {
            ctx.body = {
                success: false,
                message: '会话ID不能为空'
            };
        }
        if (!content) {
            ctx.body = {
                success: false,
                message: '消息内容不能为空'
            };
        }
        try {
            let res = await client.conversations.messages.create( conversation_id,{
                content,
                content_type:'text',
                role:'user',
            });
            ctx.body = {
                success: true,
                data: res
            };
        }
        catch (e){
            ctx.body = {
                success: false,
                message: e.message
            };
        }

    }
}
module.exports = ChatController;